வேகமான, திறமையான கோடை உருவாக்குங்கள். ரெகுலர் எக்ஸ்பிரஷன் ஆப்டிமைசேஷனுக்கான பின்தடமறிதல், பேராசை/சோம்பேறி பொருத்தம் போன்ற முக்கிய நுட்பங்களைக் கற்றுக்கொள்ளுங்கள்.
ரெகுலர் எக்ஸ்பிரஷன் ஆப்டிமைசேஷன்: ரெஜெக்ஸ் செயல்திறன் சரிப்படுத்தலில் ஒரு ஆழமான பார்வை
ரெகுலர் எக்ஸ்பிரஷன்கள், அல்லது ரெஜெக்ஸ், நவீன புரோகிராமரின் கருவிப்பெட்டியில் ஒரு தவிர்க்க முடியாத கருவியாகும். பயனர் உள்ளீட்டை சரிபார்ப்பது மற்றும் பதிவு கோப்புகளைப் பிரிப்பது முதல் சிக்கலான தேடல்-மற்றும்-மாற்று செயல்பாடுகள் மற்றும் தரவு பிரித்தெடுத்தல் வரை, அவற்றின் சக்தி மற்றும் பன்முகத்தன்மை மறுக்க முடியாதது. இருப்பினும், இந்த சக்தி ஒரு மறைக்கப்பட்ட விலையுடன் வருகிறது. ஒரு மோசமாக எழுதப்பட்ட ரெஜெக்ஸ் ஒரு அமைதியான செயல்திறன் கொலையாளியாக மாறக்கூடும், இது குறிப்பிடத்தக்க தாமதத்தை அறிமுகப்படுத்துகிறது, CPU பயன்பாட்டை அதிகரிக்கிறது, மற்றும் மோசமான சந்தர்ப்பங்களில், உங்கள் பயன்பாட்டை முடக்கிவிடும். இங்குதான் ரெகுலர் எக்ஸ்பிரஷன் ஆப்டிமைசேஷன் என்பது வெறும் 'இருந்தால் நல்லது' என்ற திறனாக இல்லாமல், வலுவான மற்றும் அளவிடக்கூடிய மென்பொருளை உருவாக்குவதற்கு ஒரு முக்கியமான திறனாகிறது.
இந்த விரிவான வழிகாட்டி உங்களை ரெஜெக்ஸ் செயல்திறன் உலகில் ஒரு ஆழமான பயணத்திற்கு அழைத்துச் செல்லும். ஒரு வெளித்தோற்றத்தில் எளிமையான பேட்டர்ன் ஏன் பேரழிவுகரமாக மெதுவாக இருக்கக்கூடும் என்பதை நாங்கள் ஆராய்வோம், ரெஜெக்ஸ் இன்ஜின்களின் உள் செயல்பாடுகளைப் புரிந்துகொள்வோம், மேலும் சரியானவை மட்டுமல்ல, மிக வேகமானவையுமான ரெகுலர் எக்ஸ்பிரஷன்களை எழுத உங்களுக்கு ஒரு சக்திவாய்ந்த கொள்கைகள் மற்றும் நுட்பங்களின் தொகுப்பை வழங்குவோம்.
'ஏன்' என்பதைப் புரிந்துகொள்ளுதல்: ஒரு தவறான ரெஜெக்ஸின் விலை
நாம் ஆப்டிமைசேஷன் நுட்பங்களுக்குள் நுழைவதற்கு முன், நாம் தீர்க்க முயற்சிக்கும் சிக்கலைப் புரிந்துகொள்வது அவசியம். ரெகுலர் எக்ஸ்பிரஷன்களுடன் தொடர்புடைய மிகக் கடுமையான செயல்திறன் சிக்கல் பேரழிவு பின்தடமறிதல் (Catastrophic Backtracking) என்று அழைக்கப்படுகிறது, இது ஒரு ரெகுலர் எக்ஸ்பிரஷன் சேவை மறுப்பு (ReDoS) பாதிப்புக்கு வழிவகுக்கும் ஒரு நிலை.
பேரழிவு பின்தடமறிதல் என்றால் என்ன?
ஒரு ரெஜெக்ஸ் இன்ஜின் ஒரு பொருத்தத்தைக் கண்டுபிடிக்க (அல்லது பொருத்தம் சாத்தியமில்லை என்று தீர்மானிக்க) விதிவிலக்காக நீண்ட நேரம் எடுக்கும்போது பேரழிவு பின்தடமறிதல் ஏற்படுகிறது. இது குறிப்பிட்ட வகை உள்ளீட்டு சரங்களுக்கு எதிராக குறிப்பிட்ட வகை பேட்டர்ன்களுடன் நிகழ்கிறது. இன்ஜின், பேட்டர்னை திருப்திப்படுத்த ஒவ்வொரு சாத்தியமான வழியையும் முயற்சி செய்து, குழப்பமான வரிசைமாற்றங்களின் ஒரு வலையில் சிக்கிக்கொள்கிறது. உள்ளீட்டு சரத்தின் நீளத்துடன் படிகளின் எண்ணிக்கை அதிவேகமாக வளரக்கூடும், இது ஒரு பயன்பாட்டு முடக்கம் போல் தோன்றும் ஒரு நிலைக்கு வழிவகுக்கிறது.
பாதிக்கப்படக்கூடிய ரெஜெக்ஸின் இந்த உன்னதமான உதாரணத்தைக் கவனியுங்கள்: ^(a+)+$
இந்த பேட்டர்ன் போதுமானளவு எளிமையானதாகத் தெரிகிறது: இது ஒன்று அல்லது அதற்கு மேற்பட்ட 'a'க்களைக் கொண்ட ஒரு சரத்தைத் தேடுகிறது. "a", "aa", மற்றும் "aaaaa" போன்ற சரங்களுக்கு இது சரியாக வேலை செய்கிறது. சிக்கல் எப்போது எழுகிறது என்றால், கிட்டத்தட்ட பொருந்தும் ஆனால் இறுதியில் தோல்வியடையும் ஒரு சரத்திற்கு எதிராக அதைச் சோதிக்கும்போது, அதாவது "aaaaaaaaaaaaaaaaaaaaaaaaaaab" போன்றது.
இது ஏன் இவ்வளவு மெதுவாக இருக்கிறது என்பதற்கான காரணம் இதோ:
- வெளிப்புற
(...)+மற்றும் உட்புறa+இரண்டுமே பேராசை அளவுருக்கள் (greedy quantifiers). - உட்புற
a+முதலில் அனைத்து 27 'a'க்களையும் பொருத்துகிறது. - வெளிப்புற
(...)+இந்த ஒற்றைப் பொருத்தத்தில் திருப்தி அடைகிறது. - பிறகு இன்ஜின் சரத்தின் இறுதி நங்கூரமான
$ஐ பொருத்த முயற்சிக்கிறது. அது தோல்வியடைகிறது કારણકે அங்கு ஒரு 'b' உள்ளது. - இப்போது, இன்ஜின் பின்தடமறிய (backtrack) வேண்டும். வெளிப்புறக் குழு ஒரு எழுத்தை விட்டுக்கொடுக்கிறது, எனவே உட்புற
a+இப்போது 26 'a'க்களைப் பொருத்துகிறது, மற்றும் வெளிப்புறக் குழுவின் இரண்டாவது மறு செய்கை கடைசி 'a' ஐ பொருத்த முயற்சிக்கிறது. இதுவும் 'b' இல் தோல்வியடைகிறது. - இன்ஜின் இப்போது 'a'க்களின் சரத்தை உட்புற
a+மற்றும் வெளிப்புற(...)+க்கு இடையில் பிரிக்க ஒவ்வொரு சாத்தியமான வழியையும் முயற்சிக்கும். N 'a'க்களைக் கொண்ட ஒரு சரத்திற்கு, அதை பிரிக்க 2N-1 வழிகள் உள்ளன. சிக்கலானது அதிவேகமானது, மற்றும் செயலாக்க நேரம் ராக்கெட் வேகத்தில் அதிகரிக்கிறது.
இந்த ஒற்றை, பாதிப்பில்லாததாகத் தோன்றும் ரெஜெக்ஸ், ஒரு CPU கோரை வினாடிகள், நிமிடங்கள் அல்லது அதற்கும் மேலாக முடக்கக்கூடும், இது மற்ற செயல்முறைகள் அல்லது பயனர்களுக்கு திறம்பட சேவையை மறுக்கிறது.
விஷயத்தின் இதயம்: ரெஜெக்ஸ் இன்ஜின்
ரெஜெக்ஸை மேம்படுத்த, உங்கள் பேட்டர்னை இன்ஜின் எவ்வாறு செயலாக்குகிறது என்பதை நீங்கள் புரிந்து கொள்ள வேண்டும். இரண்டு முதன்மை வகை ரெஜெக்ஸ் இன்ஜின்கள் உள்ளன, அவற்றின் உள் செயல்பாடுகள் செயல்திறன் பண்புகளை தீர்மானிக்கின்றன.
DFA (Deterministic Finite Automaton) இன்ஜின்கள்
DFA இன்ஜின்கள் ரெஜெக்ஸ் உலகின் வேக அரக்கர்கள். அவை உள்ளீட்டு சரத்தை இடமிருந்து வலமாக, ஒவ்வொரு எழுத்தாக ஒரே பாஸில் செயலாக்குகின்றன. எந்தவொரு குறிப்பிட்ட நேரத்திலும், தற்போதைய எழுத்தின் அடிப்படையில் அடுத்த நிலை என்னவாக இருக்கும் என்பதை ஒரு DFA இன்ஜின் சரியாக அறியும். அதாவது அது ஒருபோதும் பின்தடமறிய வேண்டியதில்லை. செயலாக்க நேரம் நேரியல் மற்றும் உள்ளீட்டு சரத்தின் நீளத்திற்கு நேரடியாக விகிதாசாரமாக உள்ளது. grep மற்றும் awk போன்ற பாரம்பரிய யூனிக்ஸ் கருவிகள் DFA-அடிப்படையிலான இன்ஜின்களைப் பயன்படுத்தும் கருவிகளின் எடுத்துக்காட்டுகள்.
நன்மைகள்: மிகவும் வேகமான மற்றும் கணிக்கக்கூடிய செயல்திறன். பேரழிவு பின்தடமறிதலால் பாதிக்கப்படாது.
தீமைகள்: வரையறுக்கப்பட்ட அம்சத் தொகுப்பு. பின்குறிப்புகள் (backreferences), லுக்அரவுண்ட்ஸ் (lookarounds) அல்லது பிடிப்பு குழுக்கள் (capturing groups) போன்ற மேம்பட்ட அம்சங்களை அவை ஆதரிக்காது, இவை பின்தடமறியும் திறனைச் சார்ந்துள்ளன.
NFA (Nondeterministic Finite Automaton) இன்ஜின்கள்
NFA இன்ஜின்கள் பைத்தான், ஜாவாஸ்கிரிப்ட், ஜாவா, சி# (.NET), ரூபி, PHP, மற்றும் பெர்ல் போன்ற நவீன நிரலாக்க மொழிகளில் பயன்படுத்தப்படும் மிகவும் பொதுவான வகையாகும். அவை "பேட்டர்ன்-இயக்கப்படுபவை", அதாவது இன்ஜின் பேட்டர்னைப் பின்தொடர்ந்து, சரத்தின் வழியாக முன்னேறுகிறது. அது ஒரு தெளிவற்ற நிலையை அடையும்போது (ஒரு εναλλαγή | அல்லது ஒரு அளவுரு *, + போன்றவை), அது ஒரு பாதையை முயற்சிக்கும். அந்தப் பாதை இறுதியில் தோல்வியுற்றால், அது கடைசி முடிவுப் புள்ளிக்கு பின்தடமறிந்து அடுத்த கிடைக்கக்கூடிய பாதையை முயற்சிக்கும்.
இந்த பின்தடமறியும் திறன்தான் NFA இன்ஜின்களை மிகவும் சக்திவாய்ந்ததாகவும், அம்சம் நிறைந்ததாகவும் ஆக்குகிறது, இது லுக்அரவுண்ட்ஸ் மற்றும் பின்குறிப்புகளுடன் சிக்கலான பேட்டர்ன்களை செயல்படுத்துகிறது. இருப்பினும், இதுவே அவற்றின் அகில்லெஸின் குதிகால் ஆகும், ஏனெனில் இதுவே பேரழிவு பின்தடமறிதலை செயல்படுத்தும் பொறிமுறையாகும்.
இந்த வழிகாட்டியின் மீதமுள்ள பகுதிக்கு, எங்கள் ஆப்டிமைசேஷன் நுட்பங்கள் NFA இன்ஜினை அடக்குவதில் கவனம் செலுத்தும், ஏனெனில் டெவலப்பர்கள் பெரும்பாலும் இங்குதான் செயல்திறன் சிக்கல்களை எதிர்கொள்கின்றனர்.
NFA இன்ஜின்களுக்கான முக்கிய ஆப்டிமைசேஷன் கொள்கைகள்
இப்போது, உயர் செயல்திறன் கொண்ட ரெகுலர் எக்ஸ்பிரஷன்களை எழுத நீங்கள் பயன்படுத்தக்கூடிய நடைமுறை, செயல்படுத்தக்கூடிய நுட்பங்களுக்குள் நுழைவோம்.
1. குறிப்பாக இருங்கள்: துல்லியத்தின் சக்தி
மிகவும் பொதுவான செயல்திறன் எதிர்-பேட்டர்ன் என்பது .* போன்ற மிகவும் பொதுவான வைல்டு கார்டுகளைப் பயன்படுத்துவதாகும். புள்ளி . (கிட்டத்தட்ட) எந்த எழுத்துடனும் பொருந்துகிறது, மற்றும் நட்சத்திரக்குறி * என்பது "பூஜ்யம் அல்லது அதற்கு மேற்பட்ட முறை" என்று பொருள். இணைந்தால், அவை இன்ஜினை பேராசையுடன் சரத்தின் மீதமுள்ள முழு பகுதியையும் உட்கொண்டு, பின்னர் பேட்டர்னின் மீதமுள்ள பகுதி பொருந்துகிறதா என்று பார்க்க ஒவ்வொரு எழுத்தாக பின்தடமறும்படி அறிவுறுத்துகின்றன. இது நம்பமுடியாத அளவிற்கு திறனற்றது.
தவறான உதாரணம் (ஒரு HTML தலைப்பைப் பிரித்தல்):
<title>.*</title>
ஒரு பெரிய HTML ஆவணத்திற்கு எதிராக, .* முதலில் கோப்பின் இறுதி வரை எல்லாவற்றையும் பொருத்தும். பின்னர், அது கடைசி </title> ஐக் கண்டுபிடிக்கும் வரை, ஒவ்வொரு எழுத்தாக பின்தடமறியும். இது நிறைய தேவையற்ற வேலை.
நல்ல உதாரணம் (ஒரு மறுக்கப்பட்ட எழுத்து வகுப்பைப் பயன்படுத்துதல்):
<title>[^<]*</title>
இந்த பதிப்பு மிகவும் திறமையானது. மறுக்கப்பட்ட எழுத்து வகுப்பு [^<]* என்பது "பூஜ்யம் அல்லது அதற்கு மேற்பட்ட முறை '<' இல்லாத எந்த எழுத்தையும் பொருத்து" என்று பொருள். இன்ஜின் முன்னோக்கி நகர்ந்து, முதல் '<' ஐ அடையும் வரை எழுத்துக்களை உட்கொள்கிறது. அது ஒருபோதும் பின்தடமறிய வேண்டியதில்லை. இது ஒரு நேரடி, தெளிவான அறிவுறுத்தல், இது ஒரு பெரிய செயல்திறன் ஆதாயத்தை விளைவிக்கிறது.
2. பேராசை vs. சோம்பேறித்தனம்: கேள்விக்குறியின் சக்தி
ரெஜெக்ஸில் உள்ள அளவுருக்கள் இயல்பாக பேராசை கொண்டவை. அதாவது அவை ஒட்டுமொத்த பேட்டர்ன் பொருந்த அனுமதிக்கும் வரை முடிந்தவரை அதிக உரையை பொருத்துகின்றன.
- பேராசை:
*,+,?,{n,m}
அதற்குப் பிறகு ஒரு கேள்விக்குறியைச் சேர்ப்பதன் மூலம் எந்தவொரு அளவுருவையும் சோம்பேறியாக மாற்றலாம். ஒரு சோம்பேறி அளவுரு முடிந்தவரை குறைந்த உரையை பொருத்துகிறது.
- சோம்பேறி:
*?,+?,??,{n,m}?
உதாரணம்: தடிமனான குறிச்சொற்களைப் பொருத்துதல்
உள்ளீட்டு சரம்: <b>First</b> and <b>Second</b>
- பேராசை பேட்டர்ன்:
<b>.*</b>
இது பொருந்துவது:<b>First</b> and <b>Second</b>..*பேராசையுடன் கடைசி</b>வரை எல்லாவற்றையும் உட்கொண்டது. - சோம்பேறி பேட்டர்ன்:
<b>.*?</b>
இது முதல் முயற்சியில்<b>First</b>ஐப் பொருத்தும், மற்றும் நீங்கள் மீண்டும் தேடினால்<b>Second</b>ஐப் பொருத்தும்..*?பேட்டர்னின் மீதமுள்ள பகுதியை (</b>) பொருத்த அனுமதிக்கத் தேவையான குறைந்தபட்ச எழுத்துக்களைப் பொருத்தியது.
சோம்பேறித்தனம் சில பொருத்த சிக்கல்களைத் தீர்க்க முடியும் என்றாலும், அது செயல்திறனுக்கான ஒரு வெள்ளி குண்டு அல்ல. ஒரு சோம்பேறி பொருத்தத்தின் ஒவ்வொரு படிக்கும், பேட்டர்னின் அடுத்த பகுதி பொருந்துகிறதா என்பதை இன்ஜின் சரிபார்க்க வேண்டும். ஒரு மிகவும் குறிப்பிட்ட பேட்டர்ன் (முந்தைய புள்ளியிலிருந்து மறுக்கப்பட்ட எழுத்து வகுப்பு போன்றவை) பெரும்பாலும் ஒரு சோம்பேறி பேட்டர்னை விட வேகமானது.
செயல்திறன் வரிசை (வேகமானது முதல் மெதுவானது வரை):
- குறிப்பிட்ட/மறுக்கப்பட்ட எழுத்து வகுப்பு:
<b>[^<]*</b> - சோம்பேறி அளவுரு:
<b>.*?</b> - நிறைய பின்தடமறியும் பேராசை அளவுரு:
<b>.*</b>
3. பேரழிவு பின்தடமறிதலைத் தவிர்க்கவும்: உள்ளமைக்கப்பட்ட அளவுருக்களை அடக்குதல்
ஆரம்ப எடுத்துக்காட்டில் நாம் பார்த்தது போல, பேரழிவு பின்தடமறிதலின் நேரடிக் காரணம், ஒரே உரையை பொருத்தக்கூடிய மற்றொரு அளவுருவைக் கொண்ட ஒரு அளவுபடுத்தப்பட்ட குழுவைக் கொண்ட ஒரு பேட்டர்ன் ஆகும். உள்ளீட்டு சரத்தைப் பிரிக்க பல வழிகளைக் கொண்ட ஒரு தெளிவற்ற சூழ்நிலையை இன்ஜின் எதிர்கொள்கிறது.
சிக்கலான பேட்டர்ன்கள்:
(a+)+(a*)*(a|aa)+(a|b)*உள்ளீட்டு சரம் பல 'a'க்கள் மற்றும் 'b'க்களைக் கொண்டிருக்கும்போது.
இதற்கான தீர்வு, பேட்டர்னை தெளிவானதாக மாற்றுவதாகும். ஒரு குறிப்பிட்ட சரத்தைப் பொருத்த இன்ஜினுக்கு ஒரே ஒரு வழி மட்டுமே இருப்பதை நீங்கள் உறுதி செய்ய வேண்டும்.
4. அணுநிலை குழுக்கள் மற்றும் உடைமை அளவுருக்களைத் தழுவுங்கள்
உங்கள் எக்ஸ்பிரஷன்களிலிருந்து பின்தடமறிதலை அகற்றுவதற்கான மிகவும் சக்திவாய்ந்த நுட்பங்களில் இதுவும் ஒன்றாகும். அணுநிலை குழுக்கள் மற்றும் உடைமை அளவுருக்கள் இன்ஜினுக்குச் சொல்கின்றன: "நீங்கள் பேட்டர்னின் இந்தப் பகுதியைப் பொருத்தியவுடன், எழுத்துக்கள் எதையும் ஒருபோதும் திருப்பிக் கொடுக்காதீர்கள். இந்த எக்ஸ்பிரஷனுக்குள் பின்தடமறையாதீர்கள்."
உடைமை அளவுருக்கள் (Possessive Quantifiers)
ஒரு சாதாரண அளவுருவுக்குப் பிறகு + சேர்ப்பதன் மூலம் ஒரு உடைமை அளவுரு உருவாக்கப்படுகிறது (எ.கா., *+, ++, ?+, {n,m}+). அவை ஜாவா, PCRE (PHP, R), மற்றும் ரூபி போன்ற இன்ஜின்களால் ஆதரிக்கப்படுகின்றன.
உதாரணம்: 'a' ஐத் தொடர்ந்து ஒரு எண்ணைப் பொருத்துதல்
உள்ளீட்டு சரம்: 12345
- சாதாரண ரெஜெக்ஸ்:
\d+a\d+"12345" ஐப் பொருத்துகிறது. பின்னர், இன்ஜின் 'a' ஐப் பொருத்த முயற்சித்து தோல்வியடைகிறது. அது பின்தடமறைகிறது, எனவே\d+இப்போது "1234" ஐப் பொருத்துகிறது, மற்றும் அது '5' க்கு எதிராக 'a' ஐப் பொருத்த முயற்சிக்கிறது.\d+அதன் அனைத்து எழுத்துக்களையும் விட்டுக்கொடுக்கும் வரை இது தொடர்கிறது. தோல்வியடைவதற்கு இது நிறைய வேலை. - உடைமை ரெஜெக்ஸ்:
\d++a\d++உடைமையுடன் "12345" ஐப் பொருத்துகிறது. இன்ஜின் பின்னர் 'a' ஐப் பொருத்த முயற்சித்து தோல்வியடைகிறது. அளவுரு உடைமையாக இருந்ததால், இன்ஜின்\d++பகுதிக்குள் பின்தடமறிய தடைசெய்யப்பட்டுள்ளது. அது உடனடியாக தோல்வியடைகிறது. இது 'விரைவில் தோல்வியடைதல்' என்று அழைக்கப்படுகிறது மற்றும் இது மிகவும் திறமையானது.
அணுநிலை குழுக்கள் (Atomic Groups)
அணுநிலை குழுக்கள் (?>...) என்ற தொடரியலைக் கொண்டுள்ளன மற்றும் உடைமை அளவுருக்களை விட பரவலாக ஆதரிக்கப்படுகின்றன (எ.கா., .NET இல், பைத்தானின் புதிய `regex` தொகுதியில்). அவை உடைமை அளவுருக்களைப் போலவே செயல்படுகின்றன, ஆனால் ஒரு முழு குழுவிற்கும் பொருந்தும்.
(?>\d+)a என்ற ரெஜெக்ஸ் செயல்பாட்டு ரீதியாக \d++a க்கு சமமானது. அசல் பேரழிவு பின்தடமறிதல் சிக்கலைத் தீர்க்க நீங்கள் அணுநிலை குழுக்களைப் பயன்படுத்தலாம்:
அசல் சிக்கல்: (a+)+
அணுநிலை தீர்வு: ((?>a+))+
இப்போது, உட்புற குழு (?>a+) 'a'க்களின் ஒரு வரிசையைப் பொருத்தும் போது, அது வெளிப்புறக் குழு மீண்டும் முயற்சி செய்ய அவற்றை ஒருபோதும் விட்டுக்கொடுக்காது. இது தெளிவற்ற தன்மையை நீக்கி, அதிவேக பின்தடமறிதலைத் தடுக்கிறது.
5. மாற்றுகளின் வரிசை முக்கியமானது
ஒரு NFA இன்ஜின் ஒரு மாற்றை (`|` பைப்பைப் பயன்படுத்தி) சந்திக்கும்போது, அது மாற்றுகளை இடமிருந்து வலமாக முயற்சிக்கிறது. அதாவது நீங்கள் மிகவும் சாத்தியமான மாற்றை முதலில் வைக்க வேண்டும்.
உதாரணம்: ஒரு கட்டளையைப் பிரித்தல்
நீங்கள் கட்டளைகளைப் பிரிப்பதாக கற்பனை செய்து பாருங்கள், மற்றும் `GET` கட்டளை 80% நேரத்திலும், `SET` 15% நேரத்திலும், மற்றும் `DELETE` 5% நேரத்திலும் தோன்றும் என்று உங்களுக்குத் தெரியும்.
குறைந்த திறன்: ^(DELETE|SET|GET)
உங்கள் உள்ளீடுகளில் 80% இல், இன்ஜின் முதலில் `DELETE` ஐப் பொருத்த முயற்சிக்கும், தோல்வியடையும், பின்தடமறியும், `SET` ஐப் பொருத்த முயற்சிக்கும், தோல்வியடையும், பின்தடமறியும், இறுதியாக `GET` உடன் வெற்றிபெறும்.
அதிக திறன்: ^(GET|SET|DELETE)
இப்போது, 80% நேரத்தில், இன்ஜின் முதல் முயற்சியிலேயே ஒரு பொருத்தத்தைப் பெறுகிறது. இந்த சிறிய மாற்றம் மில்லியன் கணக்கான வரிகளைச் செயலாக்கும்போது ஒரு குறிப்பிடத்தக்க தாக்கத்தை ஏற்படுத்தும்.
6. உங்களுக்கு பிடிப்பு தேவைப்படாதபோது பிடிக்காத குழுக்களைப் பயன்படுத்தவும்
ரெஜெக்ஸில் உள்ள அடைப்புக்குறிகள் (...) இரண்டு விஷயங்களைச் செய்கின்றன: அவை ஒரு துணை-பேட்டர்னைக் குழுவாக்குகின்றன, மேலும் அந்த துணை-பேட்டர்னுடன் பொருந்திய உரையைப் பிடிக்கின்றன. இந்த பிடிக்கப்பட்ட உரை பின்னர் பயன்படுத்த நினைவகத்தில் சேமிக்கப்படுகிறது (எ.கா., `\1` போன்ற பின்குறிப்புகளில் அல்லது அழைக்கும் கோடால் பிரித்தெடுப்பதற்கு). இந்த சேமிப்பகத்திற்கு ஒரு சிறிய ஆனால் அளவிடக்கூடிய மேல்நிலைச் செலவு உள்ளது.
உங்களுக்கு குழுவாக்கும் நடத்தை மட்டுமே தேவைப்பட்டு, உரையைப் பிடிக்கத் தேவையில்லை என்றால், ஒரு பிடிக்காத குழுவைப் பயன்படுத்தவும்: (?:...).
பிடிப்பது: (https?|ftp)://([^/]+)
இது "http" மற்றும் டொமைன் பெயரைத் தனித்தனியாகப் பிடிக்கிறது.
பிடிக்காதது: (?:https?|ftp)://([^/]+)
இங்கு, `://` சரியாகப் பொருந்தும் வகையில் `https?|ftp` ஐ நாம் இன்னும் குழுவாக்குகிறோம், ஆனால் பொருந்தும் நெறிமுறையை நாம் சேமிக்கவில்லை. நீங்கள் டொமைன் பெயரை (அது குழு 1 இல் உள்ளது) பிரித்தெடுப்பதில் மட்டுமே அக்கறை கொண்டிருந்தால் இது சற்று திறமையானது.
மேம்பட்ட நுட்பங்கள் மற்றும் இன்ஜின்-சார்ந்த குறிப்புகள்
லுக்அரவுண்ட்ஸ்: சக்தி வாய்ந்தது ஆனால் கவனமாகப் பயன்படுத்தவும்
லுக்அரவுண்ட்ஸ் (லுக்அஹெட் (?=...), (?!...) மற்றும் லுக்பிஹைண்ட் (?<=...), (?) பூஜ்ஜிய-அகல உறுதிப்படுத்தல்கள். அவை எந்த எழுத்தையும் உண்மையில் உட்கொள்ளாமல் ஒரு நிபந்தனையைச் சரிபார்க்கின்றன. இது சூழலை சரிபார்ப்பதற்கு மிகவும் திறமையானதாக இருக்கும்.
உதாரணம்: கடவுச்சொல் சரிபார்ப்பு
ஒரு இலக்கத்தைக் கொண்டிருக்க வேண்டிய கடவுச்சொல்லை சரிபார்க்க ஒரு ரெஜெக்ஸ்:
^(?=.*\d).{8,}$
இது மிகவும் திறமையானது. லுக்அஹெட் (?=.*\d) ஒரு இலக்கம் இருக்கிறதா என்பதை உறுதிசெய்ய முன்னோக்கி ஸ்கேன் செய்கிறது, பின்னர் கர்சர் தொடக்கத்திற்கு மீட்டமைக்கப்படுகிறது. பேட்டர்னின் முக்கிய பகுதியான .{8,}, பின்னர் வெறுமனே 8 அல்லது அதற்கு மேற்பட்ட எழுத்துக்களைப் பொருத்த வேண்டும். இது பெரும்பாலும் ஒரு சிக்கலான, ஒற்றை-பாதை பேட்டர்னை விட சிறந்தது.
முன்-கணக்கீடு மற்றும் தொகுத்தல்
பெரும்பாலான நிரலாக்க மொழிகள் ஒரு ரெகுலர் எக்ஸ்பிரஷனை "தொகுக்க" ஒரு வழியை வழங்குகின்றன. அதாவது இன்ஜின் பேட்டர்ன் சரத்தை ஒரு முறை பிரித்து, ஒரு மேம்படுத்தப்பட்ட உள் பிரதிநிதித்துவத்தை உருவாக்குகிறது. நீங்கள் ஒரே ரெஜெக்ஸை பலமுறை பயன்படுத்தினால் (எ.கா., ஒரு லூப்பிற்குள்), நீங்கள் எப்போதும் அதை லூப்பிற்கு வெளியே ஒரு முறை தொகுக்க வேண்டும்.
பைத்தான் உதாரணம்:
import re
# ரெஜெக்ஸை ஒரு முறை தொகுக்கவும்
log_pattern = re.compile(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
for line in log_file:
# தொகுக்கப்பட்ட பொருளைப் பயன்படுத்தவும்
match = log_pattern.search(line)
if match:
print(match.group(1))
இதைச் செய்யத் தவறினால், இன்ஜின் ஒவ்வொரு மறு செய்கையிலும் சரம் பேட்டர்னை மீண்டும் பிரிக்க வேண்டிய கட்டாயத்தில் உள்ளது, இது CPU சுழற்சிகளின் குறிப்பிடத்தக்க வீணடிப்பாகும்.
ரெஜெக்ஸ் விவரக்குறிப்பு மற்றும் பிழைத்திருத்தத்திற்கான நடைமுறை கருவிகள்
கோட்பாடு சிறந்தது, ஆனால் பார்ப்பது நம்புவது. செயல்திறனைப் புரிந்துகொள்வதற்கு நவீன ஆன்லைன் ரெஜெக்ஸ் சோதனையாளர்கள் விலைமதிப்பற்ற கருவிகள்.
regex101.com போன்ற வலைத்தளங்கள் ஒரு "ரெஜெக்ஸ் பிழைத்திருத்தி" அல்லது "படி விளக்கம்" அம்சத்தை வழங்குகின்றன. நீங்கள் உங்கள் ரெஜெக்ஸ் மற்றும் ஒரு சோதனை சரத்தை ஒட்டலாம், அது NFA இன்ஜின் சரத்தை எவ்வாறு செயலாக்குகிறது என்பதற்கான படிப்படியான தடயத்தை உங்களுக்கு வழங்கும். இது ஒவ்வொரு போட்டி முயற்சி, தோல்வி, மற்றும் பின்தடமறிதலையும் வெளிப்படையாகக் காட்டுகிறது. உங்கள் ரெஜெக்ஸ் ஏன் மெதுவாக இருக்கிறது என்பதை காட்சிப்படுத்தவும், நாங்கள் விவாதித்த ஆப்டிமைசேஷன்களின் தாக்கத்தை சோதிக்கவும் இதுவே சிறந்த வழியாகும்.
ரெஜெக்ஸ் ஆப்டிமைசேஷனுக்கான ஒரு நடைமுறை சரிபார்ப்பு பட்டியல்
ஒரு சிக்கலான ரெஜெக்ஸை வரிசைப்படுத்தும் முன், இந்த மன சரிபார்ப்பு பட்டியலின் மூலம் அதை இயக்கவும்:
- குறிப்பிட்ட தன்மை: ஒரு சோம்பேறி
.*?அல்லது பேராசை.*ஐப் பயன்படுத்தியுள்ளேனா, அங்கு[^"\r\n]*போன்ற மிகவும் குறிப்பிட்ட மறுக்கப்பட்ட எழுத்து வகுப்பு வேகமாகவும் பாதுகாப்பாகவும் இருக்குமா? - பின்தடமறிதல்: என்னிடம்
(a+)+போன்ற உள்ளமைக்கப்பட்ட அளவுருக்கள் உள்ளதா? சில உள்ளீடுகளில் பேரழிவு பின்தடமறிதலுக்கு வழிவகுக்கும் தெளிவின்மை உள்ளதா? - உடைமை: மறுமதிப்பீடு செய்யப்படக்கூடாது என்று எனக்குத் தெரிந்த ஒரு துணை-பேட்டர்னுக்குள் பின்தடமறிவதைத் தடுக்க நான் ஒரு அணுநிலை குழு
(?>...)அல்லது ஒரு உடைமை அளவுரு*+ஐப் பயன்படுத்த முடியுமா? - மாற்றுகள்: எனது
(a|b|c)மாற்றுகளில், மிகவும் பொதுவான மாற்று முதலில் பட்டியலிடப்பட்டுள்ளதா? - பிடித்தல்: எனது அனைத்து பிடிக்கும் குழுக்களும் எனக்குத் தேவையா? மேல்நிலைச் செலவைக் குறைக்க சிலவற்றை பிடிக்காத குழுக்களாக
(?:...)மாற்ற முடியுமா? - தொகுத்தல்: நான் இந்த ரெஜெக்ஸை ஒரு லூப்பில் பயன்படுத்தினால், அதை நான் முன்-தொகுக்கிறேனா?
வழக்கு ஆய்வு: ஒரு பதிவு பகுப்பாய்வியை மேம்படுத்துதல்
அனைத்தையும் ஒன்றாக இணைப்போம். நாம் ஒரு நிலையான வலை சேவையக பதிவு வரியைப் பிரிப்பதாக கற்பனை செய்து பாருங்கள்.
பதிவு வரி: 127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326
முன் (மெதுவான ரெஜெக்ஸ்):
^(\S+) (\S+) (\S+) \[(.*)\] "(.*)" (\d+) (\d+)$
இந்த பேட்டர்ன் செயல்படும் ஆனால் திறனற்றது. தேதி மற்றும் கோரிக்கை சரத்திற்கான (.*) கணிசமாக பின்தடமறியும், குறிப்பாக தவறான வடிவமைப்பு கொண்ட பதிவு வரிகள் இருந்தால்.
பின் (மேம்படுத்தப்பட்ட ரெஜெக்ஸ்):
^(\S+) (\S+) (\S+) \[[^\]]+\] "(?:GET|POST|HEAD) ([^ "]+) HTTP/[\d.]+" (\d{3}) (\d+)$
மேம்பாடுகள் விளக்கப்பட்டுள்ளன:
\[(.*)\]என்பது\[[^\]]+\]ஆக மாறியது. பொதுவான, பின்தடமறியும்.*ஐ மூடும் அடைப்புக்குறியைத் தவிர வேறு எதையும் பொருந்தும் ஒரு மிகவும் குறிப்பிட்ட மறுக்கப்பட்ட எழுத்து வகுப்புடன் மாற்றினோம். பின்தடமறியல் தேவையில்லை."(.*)"என்பது"(?:GET|POST|HEAD) ([^ "]+) HTTP/[\d.]+"ஆக மாறியது. இது ஒரு மிகப்பெரிய முன்னேற்றம்.- நாங்கள் எதிர்பார்க்கும் HTTP முறைகளைப் பற்றி வெளிப்படையாக இருக்கிறோம், ஒரு பிடிக்காத குழுவைப் பயன்படுத்தி.
- ஒரு பொதுவான வைல்டு கார்டுக்கு பதிலாக URL பாதையை
[^ "]+(ஒரு இடம் அல்லது மேற்கோள் குறி இல்லாத ஒன்று அல்லது அதற்கு மேற்பட்ட எழுத்துக்கள்) உடன் பொருத்துகிறோம். - நாங்கள் HTTP நெறிமுறை வடிவமைப்பைக் குறிப்பிடுகிறோம்.
- நிலை குறியீட்டிற்கான
(\d+)என்பது(\d{3})ஆக இறுக்கப்பட்டது, ஏனெனில் HTTP நிலை குறியீடுகள் எப்போதும் மூன்று இலக்கங்கள்.
'பின்' பதிப்பு வியத்தகு முறையில் வேகமாகவும் ReDoS தாக்குதல்களிலிருந்து பாதுகாப்பாகவும் இருப்பது மட்டுமல்லாமல், பதிவு வரியின் வடிவமைப்பை மிகவும் கண்டிப்பாக சரிபார்ப்பதால் இது மிகவும் வலுவானதாகவும் உள்ளது.
முடிவுரை
ரெகுலர் எக்ஸ்பிரஷன்கள் ஒரு இருமுனை வாள். கவனத்துடனும் அறிவுடனும் பயன்படுத்தப்பட்டால், அவை சிக்கலான உரை செயலாக்க சிக்கல்களுக்கு ஒரு நேர்த்தியான தீர்வாகும். கவனக்குறைவாகப் பயன்படுத்தப்பட்டால், அவை ஒரு செயல்திறன் கனவாக மாறக்கூடும். முக்கிய அம்சம் என்னவென்றால், NFA இன்ஜினின் பின்தடமறியும் பொறிமுறையைப் பற்றி கவனமாக இருக்க வேண்டும் மற்றும் முடிந்தவரை அடிக்கடி இன்ஜினை ஒரு ஒற்றை, தெளிவான பாதையில் வழிநடத்தும் பேட்டர்ன்களை எழுத வேண்டும்.
குறிப்பாக இருப்பதன் மூலமும், பேராசை மற்றும் சோம்பேறித்தனத்தின் பரிமாற்றங்களைப் புரிந்துகொள்வதன் மூலமும், அணுநிலை குழுக்களுடன் தெளிவற்ற தன்மையை நீக்குவதன் மூலமும், உங்கள் பேட்டர்ன்களை சோதிக்க சரியான கருவிகளைப் பயன்படுத்துவதன் மூலமும், உங்கள் ரெகுலர் எக்ஸ்பிரஷன்களை ஒரு சாத்தியமான பொறுப்பிலிருந்து உங்கள் கோடில் ஒரு சக்திவாய்ந்த மற்றும் திறமையான சொத்தாக மாற்ற முடியும். இன்றே உங்கள் ரெஜெக்ஸை விவரக்குறிப்பு செய்யத் தொடங்கி, வேகமான, நம்பகமான பயன்பாட்டைத் திறக்கவும்.